home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PC World 2008 September
/
PCWorld_2008-09_cd.bin
/
v cisle
/
sadanastroju
/
bookmark_previews-0.6.5-fx.xpi
/
chrome
/
content
/
previewService.js
< prev
next >
Wrap
Text File
|
2008-05-27
|
32KB
|
802 lines
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Bookmark Previews extension.
*
* The Initial Developer of the Original Code is
* John Marshall <JohnM555@gmail.com>.
* Portions created by the Initial Developer are Copyright (C) 2007
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
* John Marshall <JohnM555@gmail.com>
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
if (!("STATE_START" in window)){
STATE_START = Components.interfaces.nsIWebProgressListener.STATE_START;
STATE_STOP = Components.interfaces.nsIWebProgressListener.STATE_STOP;
}
var PreviewService = {
PREVIEW_WIDTH: 600,
timeouts: [],
listener : null,
bookmarks: null,
generator : null,
_prefs : null,
get prefs(){
if (!this._prefs){
this._prefs = Components.classes["@mozilla.org/preferences-service;1"].
getService(Components.interfaces.nsIPrefService);
this._prefs = this._prefs.getBranch("extensions.bookmarkpreviews.");
}
return this._prefs;
},
isFF3 : false,
/* since load is called around 7 times for some sites before it actually loads,
just cache the last isBookmark check. isBookmark might not take long, but whatever */
_lastCheck : {uri : {spec : null}, isBookmarked : false},
onLoad: function() {
var appInfo = Components.classes["@mozilla.org/xre/app-info;1"]
.getService(Components.interfaces.nsIXULAppInfo);
var versionChecker = Components.classes["@mozilla.org/xpcom/version-comparator;1"]
.getService(Components.interfaces.nsIVersionComparator);
PreviewService.isFF3 = (versionChecker.compare(appInfo.version, "3.0a") >= 0);
if (PreviewService.isFF3)
PreviewService.bookmarks = new PreviewServiceFF3();
else{
/*
Use the listener to check for redirected bookmarks.
FF3 doesn't need this because it has a better bookmarking system.
*/
PreviewService.bookmarks = new PreviewServiceFF2();
PreviewService.listener = new BookmarkPreviewsProgressListener();
PreviewService.listener.onURILoad = PreviewService.onURILoad;
PreviewService.listener.getBrowser = PreviewService.getBrowserForURI;
gBrowser.addProgressListener(PreviewService.listener,Components.interfaces.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
}
gBrowser.addEventListener('load',PreviewService.onPageLoad,true);
var versionChecker = Components.classes["@mozilla.org/xpcom/version-comparator;1"]
.getService(Components.interfaces.nsIVersionComparator);
var em = Components.classes["@mozilla.org/extensions/manager;1"]
.getService(Components.interfaces.nsIExtensionManager);
var addon = em.getItemForID("bookmarkpreviews@mozdev.org");
var currentVersion = addon.version;
var lastVersion = PreviewService.prefs.getCharPref("currentVersion");
if (lastVersion == "none") {
PreviewService.prefs.setCharPref("currentVersion", currentVersion);
PreviewService.showFirstRunDialog();
} else if (versionChecker.compare(currentVersion,lastVersion) > 0) {
PreviewService.prefs.setCharPref("currentVersion", currentVersion);
/* any upgrade code goes here */
}
},
onUnload: function() {
gBrowser.removeEventListener('load',PreviewService.onPageLoad,true);
if (!PreviewService.isFF3)
gBrowser.removeProgressListener(PreviewService.listener);
PreviewService.bookmarks.unload();
},
onPageLoad : function(event){
var doc = event.originalTarget;
if (doc instanceof Components.interfaces.nsIDOMDocument) {
if (doc.defaultView.frameElement) {
// Frame within a tab was loaded. doc should be the root document of
// the frameset.
// Find the root document:
while (doc.defaultView.frameElement) {
doc=doc.defaultView.frameElement.ownerDocument;
}
}
if (doc && doc.URL){
var uri = null;
try{/* catch malformed uri errors */
uri = makeURI(doc.URL);
}catch(e){}
if (!uri) return;
var browser = gBrowser.getBrowserForDocument(doc);
if (browser)
PreviewService.onURILoad(uri, browser);
}
}
},
onURILoad : function(uri,browser){
var isBookmarked = uri.equals(PreviewService._lastCheck.uri)?PreviewService._lastCheck.isBookmarked:PreviewService.bookmarks.isBookmarked(uri);
//dump("onuriload: "+isBookmarked+"\n");
if (isBookmarked && PreviewService.shouldCreatePreview(uri)){
if (PreviewService.timeouts[uri.spec]!=null)
clearTimeout(PreviewService.timeouts[uri.spec]);
/* Just to give it time to load a little more... */
PreviewService.timeouts[uri.spec]=setTimeout(function(){
PreviewService.timeouts[uri.spec]=null;
PreviewService.createPreviewFromBrowser(browser,uri);
},1500);
}
PreviewService._lastCheck.uri = uri;
PreviewService._lastCheck.isBookmarked = isBookmarked;
},
shouldCreatePreview : function(uri){
if (!uri || !uri.scheme) return false;
var allowHTTPS = this.prefs.getBoolPref("createForHTTPS");
var schemes = ["http","chrome"];
if (allowHTTPS) schemes.push("https");
return schemes.indexOf(uri.scheme)>-1;
},
getBrowserForURI : function(uri){
var numTabs = gBrowser.tabContainer.childNodes.length;
for(var index=0; index<numTabs; index++) {
var currentBrowser = gBrowser.getBrowserAtIndex(index);
if (uri.equals(currentBrowser.currentURI)) {
return currentBrowser;
}
}
return null;
},
bookmarkAdded : function(uri){
var currentBrowser = this.getBrowserForURI(uri);
if (currentBrowser)
this.createPreviewFromBrowser(currentBrowser);
},
createPreviewFromBrowser : function(browser, uri, aWidth, aHeight){
uri = uri ? uri : browser.currentURI;
//dump("creatpreviewfrombrowser: "+uri.spec+"\n");
var win=browser.contentWindow;
if (!win)/*the window may have closed before the timeout*/
return;
aWidth = (aWidth && aWidth!=0)?aWidth:win.innerWidth;
aHeight = (aHeight && aHeight!=0)?aHeight:win.innerHeight;
var canvas = document.createElementNS("http://www.w3.org/1999/xhtml", "canvas");
var scale=this.PREVIEW_WIDTH/(aWidth);
canvas.height = Math.floor(scale*(aHeight));
canvas.width = this.PREVIEW_WIDTH;
var ctx = canvas.getContext("2d");
ctx.save();
ctx.scale(scale, scale);
ctx.drawWindow(win, 0, 0, aWidth, aHeight,"rgb(255,255,255)");
ctx.restore();
var data = canvas.toDataURL("image/jpeg", "");
if(data && data != "") {
try {
this.bookmarks.savePreview(data,uri);
this.sendUpdateNotification(uri);
} catch(e) {
Components.utils.reportError("Bookmarks Previews: Error saving bookmark image for uri\n"+uri.spec+"\nError: "+e+"\n");
}
}
},
sendUpdateNotification : function(uri){
/* When notifying the observers right away, the observers still seem to think
that the file doesn't exist. */
//dump("send update notification\n");
setTimeout(function(){
Components.classes["@mozilla.org/observer-service;1"]
.getService(Components.interfaces.nsIObserverService)
.notifyObservers(uri, "bookmarkpreviews:preview-updated", null);
},0);
},
showFirstRunDialog : function(){
var self = this;
var strbundleService = Components.classes ["@mozilla.org/intl/stringbundle;1"]
.getService(Components.interfaces.nsIStringBundleService);
this.bundle = strbundleService.createBundle("chrome://bookmarkpreviews/locale/strings.properties");
var dialogQ = this.bundle.GetStringFromName("firstrundialog");
var dialogTitle = this.bundle.GetStringFromName("firstrundialogtitle");
/* Give it some time for the browser to actually load */
setTimeout(function(){
var prompts = Components.classes["@mozilla.org/embedcomp/prompt-service;1"]
.getService(Components.interfaces.nsIPromptService);
var result = prompts.confirm(window, dialogTitle, dialogQ);
if (result){
self.generateAllPreviews();
} else
delete this.bundle;
},2000);
},
generateAllPreviews : function(){
if (!this.generator || this.generator.status == "complete"){
this.generator = new PreviewGenerator();
this.generator.generateAllPreviews();
} else {
/* still generating */
}
}
}
function PreviewGenerator(){}
PreviewGenerator.prototype = {
LOAD_TIMEOUT : 1000 * 60,
status: null,
generateAllPreviews : function(){
this.allBookmarks = PreviewService.bookmarks.getAllBookmarks();
if (!this.allBookmarks || this.allBookmarks.length==0){
this.allBookmarks = null;
return;
}
if (!this.bundle){
var strbundleService = Components.classes ["@mozilla.org/intl/stringbundle;1"]
.getService(Components.interfaces.nsIStringBundleService);
this.bundle = strbundleService.createBundle("chrome://bookmarkpreviews/locale/strings.properties");
}
this.status = "loading";
this.curPreview = -1;
this.browser = document.getElementById("bookmarkpreviews-browser");
if (!this.browser){
this.browser = document.createElement("browser");
this.browser.setAttribute("id","bookmarkpreviews-browser");
this.browser.setAttribute("width",1);
this.browser.setAttribute("height",1);
this.browser.setAttribute("type","content");
this.browser = document.documentElement.appendChild(this.browser);
}
this.browser.hidden = false;
/* The canvas can't save flash/java so don't waste time loading it*/
this.browser.docShell.allowPlugins = false;
/* So it doesn't launch any windows as its working in the background*/
this.browser.docShell.allowJavascript = false;
/* don't throw up password dialogs */
this.browser.docShell.allowAuth = false;
this.browser.stop();
var listener = new BookmarkPreviewsProgressListener();
listener.getBrowser = function BP_GetBrowser(uri){
return document.getElementById("bookmarkpreviews-browser");
}
listener.onURILoad = this.onPreviewLoad;
listener.surpressDialogs = !PreviewService.isFF3;
this.browser.addProgressListener(listener,Components.interfaces.nsIWebProgress.NOTIFY_STATE_DOCUMENT);
this.previewGenListener = listener;
this.browser.addEventListener("load",this,true);
this.loadNextBookmark();
},
onPreviewLoad : function(uri){
var self = PreviewService.generator;
if (self.status == "loading" && uri.equals(self.allBookmarks[self.curPreview])){
if (self.generateTimeout!=null){
clearTimeout(self.generateTimeout);
}
self.generateTimeout=setTimeout(function(){
try{
if (self.status == "loading")
self.generatePreview(uri,self.browser);
}catch(e){
dump("previewload: error: "+e);
}
},1500);
}
},
generatePreview : function(uri){
this.generateTimeout = null;
var browser = this.browser;
if (!browser || !browser.stop){
return;
}
if (browser){
browser.stop();
PreviewService.createPreviewFromBrowser(browser,uri,gBrowser.boxObject.width,gBrowser.boxObject.height);
}
this.loadNextBookmark();
},
handleEvent : function(event){
if (event.type == "load")
this.onPageLoad(event);
},
onPageLoad : function(event){
var doc = event.originalTarget;
if (doc instanceof Components.interfaces.nsIDOMDocument) {
if (doc.defaultView.frameElement) {
// Frame within a tab was loaded. doc should be the root document of
// the frameset.
// Find the root document:
while (doc.defaultView.frameElement) {
doc=doc.defaultView.frameElement.ownerDocument;
}
}
var uri = null;
try{
uri = makeURI(doc.URL);
}catch(e){}
if (!uri) return;
this.onPreviewLoad(uri);
}
},
loadNextBookmark : function(){
var uri = null;
while (!uri && this.curPreview+1<this.allBookmarks.length){
this.curPreview++;
uri = this.allBookmarks[this.curPreview];
if (!uri || !(uri.scheme=="http" || uri.scheme=="https") ||
!PreviewService.shouldCreatePreview(uri) ||
PreviewService.bookmarks.hasPreview(uri.spec)){
uri = null;
}
}
var self = this;
if (!uri){
function generatetimedout(){
try{
if (self.status!="complete")
self.generatePreviewsComplete();
}catch(e){dump("ctimedoute: "+e+"\n");}
}
self.generateTimeout = setTimeout(generatetimedout,2000);
}
else{
var statusTextFld = document.getElementById("statusbar-display");
var statustext = this.bundle.GetStringFromName("creatingpreview.statustext");
statusTextFld.label = statustext.replace("$1",(this.curPreview+1)).replace("$2",this.allBookmarks.length).replace("$3",uri.spec)
var flags = Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_HISTORY;
try{
this.browser.loadURIWithFlags(uri.spec,flags,null,null);
function timedout(){
try{
self.generatePreview(uri);
}catch(e){dump("timedoute: "+e+"\n");}
}
self.generateTimeout = setTimeout(timedout,this.LOAD_TIMEOUT);
}catch(e){
dump("BPError: "+e);
this.loadNextBookmark();
}
}
},
generatePreviewsComplete : function(){
this.status = "complete";
alert(this.bundle.GetStringFromName("previewsgenerated"));
this.browser.removeProgressListener(this.previewGenListener);
this.browser.removeEventListener("load",this,true);
//this.browser = this.browser.parentNode.removeChild(this.browser);
this.browser.hidden = true;
this.previewGenListener = null;
this.allBookmarks = null;
this.browser = null;
this.curPreview = null;
this.bundle = null;
}
}
function BookmarkPreviewsProgressListener(){
}
BookmarkPreviewsProgressListener.prototype = {
onURILoad : null,
getBrowser : null,
surpressDialogs : false,
QueryInterface: function(aIID) {
if (aIID.equals(Components.interfaces.nsIWebProgressListener) ||
aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
aIID.equals(Components.interfaces.nsISupports))
return this;
throw Components.results.NS_NOINTERFACE;
},
onStateChange: function(aProgress, aRequest, aFlag, aStatus) {
if (aFlag & STATE_START &&
aRequest && aRequest instanceof Ci.nsIChannel &&
this.surpressDialogs == true
){
aRequest.notificationCallbacks = new BookmarkPreviewsListener();
}
if(aFlag & STATE_STOP){
if (aRequest instanceof Components.interfaces.nsIChannel){
var chan = aRequest.QueryInterface(Components.interfaces.nsIChannel);
if (!chan.URI.equals(chan.originalURI)){
var browser = this.getBrowser(chan.URI);
if (browser)
this.onURILoad(chan.originalURI,browser);
}
}
}
return 0;
},
onLocationChange: function(aProgress, aRequest, aURI){},
onProgressChange: function() {return 0;},
onStatusChange: function() {return 0;},
onSecurityChange: function() {return 0;},
onLinkIconAvailable: function() {return 0;}
}
/*
Surpress cert dialogs and other errors when loading sites in the background
*/
function BookmarkPreviewsListener(callback){
this.callback = callback;
}
BookmarkPreviewsListener.prototype = {
/* Whether to load the site or not if there is an error */
load : false,
// nsIInterfaceRequestor
getInterface: function BKMKP_load_GI(aIID) {
return this.QueryInterface(aIID);
},
/* nsIBadCertListener2
return true to suppress the error message
*/
notifyCertProblem: function BKMKP_certProblem(socketInfo, status, targetSite) {
dump("bad cert - notify cert problem\n");
return true;
},
/* nsIBadCertListener
return true to load the page, false to stop loading
*/
confirmUnknownIssuer: function BKMKP_load_CUI(aSocketInfo, aCert,
aCertAddType) {
dump("bad cert issuer\n");
dump("cert url: "+(PreviewService.generator.allBookmarks[PreviewService.generator.curPreview].spec)+"\n");
return this.load;
},
confirmMismatchDomain: function BKMKP_load_CMD(aSocketInfo, aTargetURL,
aCert) {
dump("bad cert - mismatch domain\n");
dump("cert url: "+(PreviewService.generator.allBookmarks[PreviewService.generator.curPreview].spec)+"\n");
return this.load;
},
confirmCertExpired: function BKMKP_load_CCE(aSocketInfo, aCert) {
dump("notifyCertProblem - certexpired\n");
dump("cert url: "+(PreviewService.generator.allBookmarks[PreviewService.generator.curPreview].spec)+"\n");
return this.load;
},
notifyCrlNextupdate: function BKMKP_load_NCN(aSocketInfo, aTargetURL, aCert) {
dump("bad cert - crlnextupdate\n");
dump("cert url: "+(PreviewService.generator.allBookmarks[PreviewService.generator.curPreview].spec)+"\n");
},
/* nsISSLErrorListener
return true to suppress the error
*/
notifySSLError: function BKMKP_SSLError(socketInfo, error, targetSite) {
dump("ssl error\n")
dump("site url: "+(PreviewService.generator.allBookmarks[PreviewService.generator.curPreview].spec)+"\n");
return true;
},
/* nsIAuthPrompt
return false to cancel
*/
prompt : function ( dialogTitle, text, passwordRealm, savePassword, defaultText, result){
dump("prompt site url: "+(PreviewService.generator.allBookmarks[PreviewService.generator.curPreview].spec)+"\n");
return false;
},
// nsIAuthPrompt
promptUsernameAndPassword : function( dialogTitle, text, passwordRealm, savePassword, user, pwd){
dump("promptUAP site url: "+(PreviewService.generator.allBookmarks[PreviewService.generator.curPreview].spec)+"\n");
return false;
},
// nsIAuthPrompt
promptPassword : function( dialogTitle, text, passwordRealm, savePassword, pwd){
dump("promptP site url: "+(PreviewService.generator.allBookmarks[PreviewService.generator.curPreview].spec)+"\n");
return false;
},
QueryInterface: function BKMKP_loadQI(aIID) {
if (aIID.equals(Ci.nsISupports) ||
aIID.equals(Ci.nsIInterfaceRequestor) ||
aIID.equals(Ci.nsIBadCertListener) || //FF2
aIID.equals(Ci.nsIBadCertListener2) || //FF3
aIID.equals(Ci.nsISSLErrorListener) ||
aIID.equals(Ci.nsIAuthPrompt) ||
false){
return this;
}
throw Cr.NS_ERROR_NO_INTERFACE;
}
}
function PreviewServiceFF3(){
this.dir = Components.classes["@mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties)
.get("ProfD", Components.interfaces.nsIFile);
this.dir.append("bookmarkpreviews");
if (!this.dir.exists())
this.dir.create(Components.interfaces.nsIFile.DIRECTORY_TYPE,0777);
this.register();
}
PreviewServiceFF3.prototype = {
toString : function(){return "Firefox 3 Preview Service";},
txnlistener : null,
dir : null,
unload : function(){
this.unregister();
},
register : function(){
PlacesUtils.bookmarks.addObserver(this.observer, false);
},
unregister : function(){
PlacesUtils.bookmarks.removeObserver(this.observer,false);
},
isBookmarked : function(uri){
return PlacesUtils.bookmarks.getBookmarkedURIFor(uri)!=null;
},
hasPreview : function(aUrl){
return PreviewServiceUtils.getPreviewFile(aUrl,this.dir).exists();
},
savePreview : function(data,uri){
var file = PreviewServiceUtils.getPreviewFile(uri.spec,this.dir);
var io = Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
var source = io.newURI(data, "UTF8", null);
var target = io.newFileURI(file)
// prepare to save the data
var persist = Components.classes["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"]
.createInstance(Components.interfaces.nsIWebBrowserPersist);
persist.persistFlags = Components.interfaces.nsIWebBrowserPersist.PERSIST_FLAGS_REPLACE_EXISTING_FILES;
persist.persistFlags |= Components.interfaces.nsIWebBrowserPersist.PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION;
persist.saveURI(source, null, null, null, null, file);
},
/* generate all previews... */
getAllBookmarks : function(root,bkmks){
if (!root){
var roots = Application.bookmarks;
root = roots.children?roots:{children: [roots.menu,roots.toolbar,roots.unfiled]};
bkmks = [];
}
var ls = Cc["@mozilla.org/browser/livemark-service;2"]
.getService(Ci.nsILivemarkService);
root.children.forEach(function(item,idx){
if (item.type=="bookmark"){
bkmks.push(item.uri);
}
else if (item.type=="folder" && !ls.isLivemark(item.id)){
this.getAllBookmarks(item,bkmks);
}
},this);
return bkmks;
},
observer : {
get mOuter(){return PreviewService.bookmarks;},
changed: {id: null, uri: null},
/* nsINavBookmarkObserver */
onBeginUpdateBatch : function(){},
onEndUpdateBatch : function(){},
onItemAdded : function(aItemId, aFolder, aIndex){
var uri = PlacesUtils.bookmarks.getBookmarkURI(aItemId);
PreviewService.bookmarkAdded(uri);
},
/*
Since this is method is called after a bookmark is already removed we can't
get the bookmark's url. To work around this we record the uri in the itemchange
method which is called before the bookmark is removed
*/
onItemRemoved : function(aItemId, aFolder, aIndex){
if (aItemId == this.changed.id){
var uri = this.changed.uri;
if (!this.mOuter.isBookmarked(uri)){
var file = PreviewServiceUtils.getPreviewFile(uri.spec,this.mOuter.dir);
if (file.exists())
file.remove(false);
}
}
},
onItemChanged : function(aBookmarkId, aProperty, aIsAnnotationProperty, aValue){
//dump("changed bookmark - "+aBookmarkId+" - prop: "+aProperty+" ann: "+aIsAnnotationProperty+" - value: "+aValue+"\n");
if (["title","favicon","tags","cleartime","keyword","bookmarkProperties/description",
"bookmarkProperties/loadInSidebar"].indexOf(aProperty)>-1)
return;
else if (aProperty == "uri"){
//remove old... add new
//but we can't remove the old since it's already been removed
//aValue == new url and getting the bookmarked uri == the new url
try{/* catch malformed uri error */
PreviewService.bookmarkAdded(makeURI(aValue));
}catch(e){}
}
else{
this.changed.id = aBookmarkId;
this.changed.uri = PlacesUtils.bookmarks.getBookmarkURI(aBookmarkId);
}
},
onItemVisited : function(aBookmarkId, aVisitID, time){},
onItemMoved : function(aItemId, aOldParent, aOldIndex, aNewParent, aNewIndex){}
}
}
function PreviewServiceFF2(){
initServices();
initBMService();
this.bmsvc = BMSVC;
this.dir = Components.classes["@mozilla.org/file/directory_service;1"]
.getService(Components.interfaces.nsIProperties)
.get("ProfD", Components.interfaces.nsIFile);
this.dir.append("bookmarkpreviews");
if (!this.dir.exists())
this.dir.create(Components.interfaces.nsIFile.DIRECTORY_TYPE,0777);
this.register();
}
PreviewServiceFF2.prototype = {
txnlistener : null,
toString : function(){return "Firefox 3 Preview Service";},
unload : function(){
this.unregister();
},
register : function(){
var bkmkTxnSvc = Components.classes["@mozilla.org/bookmarks/transactionmanager;1"]
.getService(Components.interfaces.nsIBookmarkTransactionManager);
this.txnlistener = new BookmarkPreviewsTransactionListener(this);
bkmkTxnSvc.transactionManager.AddListener(this.txnlistener);
},
unregister : function(){
var bkmkTxnSvc = Components.classes["@mozilla.org/bookmarks/transactionmanager;1"]
.getService(Components.interfaces.nsIBookmarkTransactionManager);
bkmkTxnSvc.transactionManager.RemoveListener(this.txnlistener);
},
isBookmarked : function(uri){
var NC = "http://home.netscape.com/NC-rdf#";
var RDF = Components.classes["@mozilla.org/rdf/rdf-service;1"].getService(Components.interfaces.nsIRDFService);
var BMDS = RDF.GetDataSource("rdf:bookmarks");
var urlArc = RDF.GetResource(NC+"URL");
var elements = BMDS.GetAllResources();
while (elements.hasMoreElements()){
var ele = elements.getNext();
if(BMDS.hasArcOut(ele, urlArc)){
var target = BMDS.GetTarget(ele, urlArc, true);
var value = target.QueryInterface(Components.interfaces.nsIRDFLiteral).Value;
if(value == uri.spec){
ele.QueryInterface(Components.interfaces.nsIRDFResource);
var resParent= BMSVC.getParent(ele);
if (resParent){
var name = BookmarksUtils.getProperty(resParent, "http://home.netscape.com/NC-rdf#Name");
if (name!=""){
return true;
}
}
}
}
}
return false;
},
hasPreview : function(aUrl){
return PreviewServiceUtils.getPreviewFile(aUrl,this.dir).exists();
},
savePreview : function(data,uri,aArg){
var file = PreviewServiceUtils.getPreviewFile(uri.spec,this.dir);
var io = Components.classes["@mozilla.org/network/io-service;1"]
.getService(Components.interfaces.nsIIOService);
var source = io.newURI(data, "UTF8", null);
var target = io.newFileURI(file);
if (file.exists())
file.remove(true);
// prepare to save the data
var persist = Components.classes["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"]
.createInstance(Components.interfaces.nsIWebBrowserPersist);
persist.persistFlags = Components.interfaces.nsIWebBrowserPersist.PERSIST_FLAGS_REPLACE_EXISTING_FILES;
persist.persistFlags |= Components.interfaces.nsIWebBrowserPersist.PERSIST_FLAGS_AUTODETECT_APPLY_CONVERSION;
persist.saveURI(source, null, null, null, null, file);
},
removePreview : function(url){
try{/* catch malformed uri and file io errors */
if (!this.isBookmarked(makeURI(url))){
var file = PreviewServiceUtils.getPreviewFile(url,this.dir);
if (file.exists())
file.remove(false);
}
}catch(e){}
},
observeTransaction : function(aState, aTxn, aDo){
if (!aTxn) return;
aTxn = aTxn.wrappedJSObject;
//dump("observe transaction: "+aTxn.type+" action: "+aTxn.action+"\n");
if ((aTxn.type!="insert" && aTxn.type!="remove") || aTxn.action == "move") return;
var type = aTxn.type;
var item = aTxn.item;
var isContainer = null;
function resourceIsContainer(aResource){
var type = BookmarksUtils.resolveType(aResource);
return type.indexOf("Folder")>-1 ||
type == "Livemark" ||
false;
}
/*
When removing a bookmark folder the type is originally 'Folder' in the
'will' stage, but after it is removed the type is 'ImmutableBookmark'. We
need to check what type it is before the item is actually removed.
*/
if (aTxn.type=="remove" && aDo){
if (aState == "will"){
this._transactionItemType = resourceIsContainer(item);
return;
} else {
isContainer = this._transactionItemType;
delete this._transactionItemType;
}
} else
isContainer = resourceIsContainer(item);//RDFCU.IsContainer(BMDS, RDF.GetResource(item));
if (aState=="will") return;
var urls = [];
if (isContainer){
try{
var propArray = [];
BookmarksUtils.getAllChildren(item, propArray);
propArray.forEach(function(props,idx1){
var prop = props[1];
if (prop)
urls.push(prop.Value);
});
}
catch(e){}
}
var itemURL = null;
itemURL = aTxn.removedProp[1];
if (itemURL)
urls.push(itemURL.Value);
else{
itemURL = BookmarksUtils.getProperty(aTxn.item,aTxn.Properties[1].Value);
if (itemURL)
urls.push(itemURL);
}
urls.forEach(function(url,idx){
try{/* catch malformed uri errors */
if (((type == "insert" && aDo) || (type == "remove" && !aDo)) && url){
PreviewService.bookmarkAdded(makeURI(url));
}
else if (((type == "remove" && aDo) || (type == "insert" && !aDo)) && url){
this.removePreview(url);
}
}catch(e){}
},this);
},
/* Used for generating all previews */
getAllBookmarks : function(){
var children = [], all = [];
BookmarksUtils.getAllChildren(RDF.GetResource("NC:BookmarksRoot"),children);
for (var i = 0; i < children.length; i++){
try{
if (children[i][1] && children[i][1].Value!=null){
all.push(makeURI(children[i][1].Value));
}
}catch(e){dump(e+"\n");}
}
return all;
}
}
function BookmarkPreviewsTransactionListener(parent){
this.parent = parent;
}
BookmarkPreviewsTransactionListener.prototype = {
willDo: function (aTxmgr, aTxn) {
this.parent.observeTransaction("will", aTxn, true);
},
didDo : function (aTxmgr, aTxn) {
this.parent.observeTransaction("did", aTxn, true);
},
willUndo: function (aTxmgr, aTxn) {
this.parent.observeTransaction("will", aTxn, true);
},
didUndo : function (aTxmgr, aTxn) {
this.parent.observeTransaction("did", aTxn, false);
},
willRedo: function (aTxmgr, aTxn) {
this.parent.observeTransaction("will", aTxn, true);
},
didRedo : function (aTxmgr, aTxn) {
this.parent.observeTransaction("did", aTxn, true);
},
didMerge : function (aTxmgr, aTxn) {},
didBeginBatch : function (aTxmgr, aTxn) {},
didEndBatch : function (aTxmgr, aTxn) {
this.parent.observeTransaction("did", aTxn, true);
},
willMerge : function (aTxmgr, aTxn) {},
willBeginBatch : function (aTxmgr, aTxn) {},
willEndBatch : function (aTxmgr, aTxn) {}
}
window.addEventListener('load',function(e) { PreviewService.onLoad(e); },false);
window.addEventListener('unload',function(e) { PreviewService.onUnload(e); },false);